﻿#pragma once

#include <string>  
#include <vector> 
#include <list>

#ifndef WIN32
#include <cstring>
#endif

template<typename CHAR = char, class alloc = std::allocator<CHAR> >
class StringBuilder
{
public:
	typedef std::vector<CHAR, alloc> CharVec;
	typedef std::list<CharVec> DataList;

	StringBuilder() = default;
	StringBuilder(const std::string &str)
	{
		m_dataList.emplace_back(str.begin(), str.end());
		m_strlen += str.length();
	}

	virtual ~StringBuilder() = default;

	StringBuilder &Append(const std::string &str)
	{
		append(str);
		return *this;
	}

	void clear()
	{
		m_dataList.clear();
		m_strlen = 0;
	}

	StringBuilder& operator<<(void *ptr)
	{
		static constexpr unsigned len = sizeof(void*);
		char str[len * 4] = "\0";
		sprintf(str, "0x%p", ptr);
		return append(str);
	}

	StringBuilder& operator<<(bool val)
	{
		return append(val ? "1" : "0");
	}

	StringBuilder& operator<<(short val)
	{
		return operator<<(int(val));
	}

	StringBuilder& operator<<(int val)
	{
		auto buf = GetBuf();
		auto str = std::to_string(val);
		return append(str);
	}

	StringBuilder& operator<<(unsigned int val)
	{
		auto buf = GetBuf();
		_ultoa(val, buf, 10);
		return append(buf);
	}

	StringBuilder& operator<<(double val)
	{
		return append(std::to_string(val));
	}

	StringBuilder& operator<<(float val)
	{
		return append(std::to_string(val));
	}

	StringBuilder& operator<<(long long val)
	{
		auto buf = GetBuf();
		_i64toa(val, buf, 10);
		return append(buf);
	}

	StringBuilder& operator<<(unsigned long long val)
	{
		auto buf = GetBuf();
		_ui64toa(val, buf, 10);
		return append(buf);
	}

	StringBuilder& operator<<(const char *str)
	{
		return append(str);
	}

	StringBuilder& operator<<(const std::string_view& str)
	{
		return append(str);
	}

	StringBuilder &operator<<(const std::string &str)
	{
		return append(str);
	}

	std::string GetString()
	{
		std::string retStr;
		retStr.resize(m_strlen);
		std::string::iterator it = retStr.begin();
		int i = 0;
		for (auto it = m_dataList.begin(); it != m_dataList.end() && i < retStr.size(); ++it)
		{
			CharVec &c = *it;
			for (const CHAR &cit : c)
			{
				retStr[i++] = cit;
			}
		}

		return retStr;
	}


private:
	char* GetBuf()
	{
		static char str[50] = "\0";
		memset(str, 0, sizeof(str));
		return str;
	}

	StringBuilder& append(const char *str)
	{
		int len = (int)strlen(str);
		m_dataList.emplace_back(str, str + len);
		m_strlen += len;
		return *this;
	}

	StringBuilder& append(const std::string_view& str)
	{
		m_dataList.emplace_back(str.begin(), str.end());
		m_strlen += str.length();
		return *this;
	}

	StringBuilder &append(const std::string &str) 
	{
		m_dataList.emplace_back(str.begin(), str.end());
		m_strlen += str.length();
		return *this;
	}

	DataList m_dataList;
	size_t m_strlen = 0;
};




